#ifndef __TPS_TL_H__
#define __TPS_TL_H__

namespace Tps
{

	namespace Private
	{

		struct NullType
		{
		};

		template <typename H, typename T>
		struct TypeList
		{
			typedef H Head;
			typedef T Tail;
		};

		template <typename T>
		struct RemoveNullListTail
		{
			typedef TypeList<typename T::Head, typename RemoveNullListTail<typename T::Tail>::List> List;
		};

		template <typename T>
		struct RemoveNullListTail<TypeList<NullType, T> >
		{
			typedef NullType List;
		};

		template
		<
			typename T1,
			typename T2 = NullType,
			typename T3 = NullType,
			typename T4 = NullType,
			typename T5 = NullType,
			typename T6 = NullType,
			typename T7 = NullType,
			typename T8 = NullType,
			typename T9 = NullType,
			typename T10 = NullType,
			typename T11 = NullType,
			typename T12 = NullType,
			typename T13 = NullType,
			typename T14 = NullType,
			typename T15 = NullType
		>
		struct TypeListBuilder
			: public TypeList<T1, typename RemoveNullListTail<TypeList <
				T2, TypeList<T3, TypeList<T4, TypeList<T5, TypeList<
				T6, TypeList<T7, TypeList<T8, TypeList<T9, TypeList<
				T10, TypeList<T11, TypeList<T12, TypeList<T13, TypeList<
				T14, TypeList<T15, NullType> > > > > > > > > > > > > >
				>::List>
		{
		};

		template <typename T>
		struct ExtractFront
		{
			typedef typename T::Head Type;
		};

		template <>
		struct ExtractFront<NullType>
		{
			typedef NullType Type;
		};

		template <typename T, typename TCur, typename TList>
		struct GetTypeIndexImpl
		{
			enum { Index = GetTypeIndexImpl<T, typename ExtractFront<typename TList::Tail>::Type, typename TList::Tail>::Index + 1 };
		};

		template <typename T, typename TList>
		struct GetTypeIndexImpl<T, T, TList>
		{
			enum { Index = 0 };
		};

		template <typename T, typename TCur>
		struct GetTypeIndexImpl<T, TCur, NullType>
		{
			enum { Index = 0 };
		};

		template <typename T, typename TList>
		struct GetTypeIndex
		{
			enum { Index = GetTypeIndexImpl<T, typename ExtractFront<TList>::Type, TList>::Index };
		};

		template <typename TList>
		struct GetTypeListLength
		{
			enum { Length = GetTypeListLength<typename TList::Tail>::Length + 1 };
		};

		template <>
		struct GetTypeListLength<NullType>
		{
			enum { Length = 0 };
		};

		template <typename T>
		struct IsConstType
		{
			enum { IsConst = 0 };
		};

		template <typename T>
		struct IsConstType<T const>
		{
			enum { IsConst = 1 };
		};

		template <typename T>
		struct TypeExtractor
		{
			typedef T Type;
		};

		template <typename T>
		struct TypeExtractor<T &>
		{
			typedef T Type;
		};

		template <typename T>
		struct TypeExtractor<T *>
		{
			typedef T Type;
		};

		template <typename T>
		struct ConstCast
		{
			typedef T Type;
		};

		template <typename T>
		struct ConstCast<T const>
		{
			typedef T Type;
		};

		template <typename T>
		struct ConstCast<T const *>
		{
			typedef T * Type;
		};

		template <typename T>
		struct ConstCast<T const &>
		{
			typedef T & Type;
		};

		template <typename T>
		struct TypeWrapper
		{
			typedef T Type;
		};

		template <typename T>
		struct RemoveRef
		{
			typedef T Type;
		};

		template <typename T>
		struct RemoveRef<T &>
		{
			typedef T Type;
		};

		template <unsigned const N>
		struct TypeItem
			: public TypeItem<N - 1>
		{
		};

		template <>
		struct TypeItem<0>
		{
		};

		template <int N>
		struct IntToType
		{
			enum { Int = N };
		};

	}

}

#endif	// !__TPS_TL_H__
